home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / pexpr.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  76KB  |  1,677 lines

  1. {
  2.     $Id: pexpr.pas,v 1.2.2.1 1998/05/21 12:26:55 carl Exp $
  3.     Copyright (c) 1998 by Florian Klaempfl
  4.  
  5.     Does parsing of expression for Free Pascal
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. unit pexpr;
  24.  
  25.   interface
  26.  
  27.     uses symtable,tree;
  28.  
  29.     { reads a whole expression }
  30.     function expr : ptree;
  31.  
  32.     { reads a single factor }
  33.     function factor(getaddr : boolean) : ptree;
  34.  
  35.     { the ID token has to be consumed before calling this function }
  36.     procedure do_member_read(const sym : psym;var p1 : ptree;
  37.       var pd : pdef;var again : boolean);
  38.  
  39.     function get_intconst:longint;
  40.  
  41.     function get_stringconst:string;
  42.  
  43.   implementation
  44.  
  45.     uses
  46.        cobjects,globals,scanner,aasm,pass_1,systems,
  47.        hcodegen,types,verbose
  48.        { parser specific stuff }
  49.        ,pbase,pdecl
  50.        { processor specific stuff }
  51. {$ifdef i386}
  52.        ,i386
  53. {$endif}
  54. {$ifdef m68k}
  55.        ,m68k
  56. {$endif}
  57.        ;
  58.  
  59.     function parse_paras(_colon,in_prop_paras : boolean) : ptree;
  60.  
  61.       var
  62.          p1,p2 : ptree;
  63.          end_of_paras : ttoken;
  64.  
  65.       begin
  66.          if in_prop_paras  then
  67.            end_of_paras:=RECKKLAMMER
  68.          else
  69.            end_of_paras:=RKLAMMER;
  70.          if token=end_of_paras then
  71.            begin
  72.               parse_paras:=nil;
  73.               exit;
  74.            end;
  75.          p2:=nil;
  76.          inc(parsing_para_level);
  77.          while true do
  78.            begin
  79.               p1:=expr;
  80.               p2:=gencallparanode(p1,p2);
  81.  
  82.               { it's for the str(l:5,s); }
  83.               if _colon and (token=COLON) then
  84.                 begin
  85.                    consume(COLON);
  86.                    p1:=expr;
  87.                    p2:=gencallparanode(p1,p2);
  88.                    p2^.is_colon_para:=true;
  89.                    if token=COLON then
  90.                      begin
  91.                         consume(COLON);
  92.                         p1:=expr;
  93.                         p2:=gencallparanode(p1,p2);
  94.                         p2^.is_colon_para:=true;
  95.                      end
  96.                 end;
  97.               if token=COMMA then
  98.                 consume(COMMA)
  99.               else
  100.                 break;
  101.            end;
  102.          dec(parsing_para_level);
  103.          parse_paras:=p2;
  104.       end;
  105.  
  106.     function statement_syssym(l : longint;var pd : pdef) : ptree;
  107. {   const   regnames:array[R_EAX..R_EDI] of string[3]=
  108.              ('EAX','ECX','EDX','EBX','','','ESI','EDI'); }
  109.  
  110.       var
  111.          p1,p2 : ptree;
  112.          paras : ptree;
  113.          prev_in_args : boolean;
  114.          Store_valid : boolean;
  115.  
  116.       begin
  117.          prev_in_args:=in_args;
  118.          Store_valid:=Must_be_valid;
  119.          case l of
  120.             in_ord_x :
  121.               begin
  122.                  consume(LKLAMMER);
  123.                  in_args:=true;
  124.                  Must_be_valid:=true;
  125.                  p1:=expr;
  126.                  consume(RKLAMMER);
  127.                  do_firstpass(p1);
  128.                  p1:=geninlinenode(in_ord_x,p1);
  129.                  do_firstpass(p1);
  130.                  statement_syssym := p1;
  131.                  pd:=p1^.resulttype;
  132.               end;
  133.             in_typeof_x : begin
  134.                              consume(LKLAMMER);
  135.                              in_args:=true;
  136.                              p1:=expr;
  137.                              consume(RKLAMMER);
  138.                              pd:=voidpointerdef;
  139.                              if p1^.treetype=typen then
  140.                                begin
  141.                                   if (p1^.resulttype=nil) then
  142.                                     begin
  143.                                        Message(sym_e_type_mismatch);
  144.                                        statement_syssym:=genzeronode(errorn);
  145.                                     end
  146.                                   else
  147.                                   if p1^.resulttype^.deftype=objectdef then
  148.                                     statement_syssym:=geninlinenode(in_typeof_x,p1)
  149.                                   else
  150.                                     begin
  151.                                        Message(sym_e_type_mismatch);
  152.                                        statement_syssym:=genzeronode(errorn);
  153.                                     end;
  154.                                end
  155.                              else
  156.                                begin
  157.                                   Must_be_valid:=false;
  158.                                   do_firstpass(p1);
  159.                                   if (p1^.resulttype=nil) then
  160.                                     begin
  161.                                        Message(sym_e_type_mismatch);
  162.                                        statement_syssym:=genzeronode(errorn)
  163.                                     end
  164.                                   else
  165.                                   if p1^.resulttype^.deftype=objectdef then
  166.                                     statement_syssym:=geninlinenode(in_typeof_x,p1)
  167.                                   else
  168.                                     begin
  169.                                        Message(sym_e_type_mismatch);
  170.                                        statement_syssym:=genzeronode(errorn)
  171.                                     end;
  172.                                end;
  173.                           end;
  174.             in_sizeof_x : begin
  175.                              consume(LKLAMMER);
  176.                              in_args:=true;
  177.                              p1:=expr;
  178.                              consume(RKLAMMER);
  179.                              pd:=s32bitdef;
  180.                              if p1^.treetype=typen then
  181.                                begin
  182.                                   statement_syssym:=genordinalconstnode(
  183.                                     p1^.resulttype^.size,pd);
  184.                                   { p1 not needed !}
  185.                                   disposetree(p1);
  186.                                end
  187.                              else
  188.                                begin
  189.                                   Must_be_valid:=false;
  190.                                   do_firstpass(p1);
  191.                                   if p1^.resulttype^.deftype<>objectdef then
  192.                                     begin
  193.                                        statement_syssym:=genordinalconstnode(
  194.                                          p1^.resulttype^.size,pd);
  195.                                        { p1 not needed !}
  196.                                        disposetree(p1);
  197.                                     end
  198.                                   else
  199.                                     begin
  200.                                        statement_syssym:=geninlinenode(in_sizeof_x,p1);
  201.                                     end;
  202.                                end;
  203.                           end;
  204.             in_assigned_x : begin
  205.                                consume(LKLAMMER);
  206.                                in_args:=true;
  207.                                p1:=expr;
  208.                                Must_be_valid:=true;
  209.                                do_firstpass(p1);
  210.                                case p1^.resulttype^.deftype of
  211.                                  pointerdef,procvardef,
  212.                                  classrefdef:
  213.                                    ;
  214.                                  objectdef:
  215.                                    if not(pobjectdef(p1^.resulttype)^.isclass) then
  216.                                      Message(parser_e_illegal_parameter_list);
  217.                                  else Message(parser_e_illegal_parameter_list);
  218.                                end;
  219.                                p2:=gencallparanode(p1,nil);
  220.                                p2:=geninlinenode(in_assigned_x,p2);
  221.                                consume(RKLAMMER);
  222.                                pd:=booldef;
  223.                                statement_syssym:=p2;
  224.                             end;
  225.             in_ofs_x : begin
  226.                           consume(LKLAMMER);
  227.                           in_args:=true;
  228.                           p1:=expr;
  229.                           p1:=gensinglenode(addrn,p1);
  230.                           Must_be_valid:=false;
  231.                           do_firstpass(p1);
  232.                         { Ofs() returns a longint, not a pointer }
  233.                           p1^.resulttype:=u32bitdef;
  234.                           pd:=p1^.resulttype;
  235.                           consume(RKLAMMER);
  236.                           statement_syssym:=p1;
  237.                        end;
  238.             in_seg_x : begin
  239.                           consume(LKLAMMER);
  240.                           in_args:=true;
  241.                           p1:=expr;
  242.                           do_firstpass(p1);
  243.                           if p1^.location.loc<>LOC_REFERENCE then
  244.                             Message(cg_e_illegal_expression);
  245.                           p1:=genordinalconstnode(0,s32bitdef);
  246.                           Must_be_valid:=false;
  247.                           pd:=s32bitdef;
  248.                           consume(RKLAMMER);
  249.                           statement_syssym:=p1;
  250.                        end;
  251.             in_high_x,
  252.             in_low_x : begin
  253.                           consume(LKLAMMER);
  254.                           in_args:=true;
  255.                           p1:=expr;
  256.                           do_firstpass(p1);
  257.                           Must_be_valid:=false;
  258.                           p2:=geninlinenode(l,p1);
  259.                           consume(RKLAMMER);
  260.                           pd:=s32bitdef;
  261.                           statement_syssym:=p2;
  262.                        end;
  263.             in_succ_x,
  264.             in_pred_x : begin
  265.                           consume(LKLAMMER);
  266.                           in_args:=true;
  267.                           p1:=expr;
  268.                           do_firstpass(p1);
  269.                           Must_be_valid:=false;
  270.                           p2:=geninlinenode(l,p1);
  271.                           consume(RKLAMMER);
  272.                           pd:=p1^.resulttype;
  273.                           statement_syssym:=p2;
  274.                        end;
  275.             in_inc_x,
  276.             in_dec_x : begin
  277.                           consume(LKLAMMER);
  278.                           in_args:=true;
  279.                           p1:=expr;
  280.                           p2:=gencallparanode(p1,nil);
  281.                           Must_be_valid:=false;
  282.                           if token=COMMA then
  283.                             begin
  284.                                consume(COMMA);
  285.                                p1:=expr;
  286.                                p2:=gencallparanode(p1,p2);
  287.                             end;
  288.                           statement_syssym:=geninlinenode(l,p2);
  289.                           consume(RKLAMMER);
  290.                           pd:=voiddef;
  291.                        end;
  292.             in_concat_x : begin
  293.                              consume(LKLAMMER);
  294.                              in_args:=true;
  295.                              p2:=nil;
  296.                              while true do
  297.                                begin
  298.                                   p1:=expr;
  299.                                   Must_be_valid:=true;
  300.                                   do_firstpass(p1);
  301.                                   if not((p1^.resulttype^.deftype=stringdef) or
  302.                                          ((p1^.resulttype^.deftype=orddef) and
  303.                                           (porddef(p1^.resulttype)^.typ=uchar)
  304.                                          )
  305.                                     ) then Message(parser_e_illegal_parameter_list);
  306.                                   if p2<>nil then
  307.                                     p2:=gennode(addn,p2,p1)
  308.                                   else p2:=p1;
  309.                                   if token=COMMA then
  310.                                     consume(COMMA)
  311.                                   else break;
  312.                                end;
  313.                              consume(RKLAMMER);
  314.                              pd:=cstringdef;
  315.                              statement_syssym:=p2;
  316.                           end;
  317.             in_read_x,
  318.             in_readln_x : begin
  319.                              if token=LKLAMMER then
  320.                                begin
  321.                                   consume(LKLAMMER);
  322.                                   in_args:=true;
  323.                                   Must_be_valid:=false;
  324.                                   paras:=parse_paras(false,false);
  325.                                   consume(RKLAMMER);
  326.                                end
  327.                              else
  328.                                paras:=nil;
  329.                              pd:=voiddef;
  330.                              p1:=geninlinenode(l,paras);
  331.                              do_firstpass(p1);
  332.                              statement_syssym := p1;
  333.                           end;
  334.             in_write_x,
  335.             in_writeln_x : begin
  336.                              if token=LKLAMMER then
  337.                                begin
  338.                                   consume(LKLAMMER);
  339.                                   in_args:=true;
  340.                                   Must_be_valid:=true;
  341.                                   paras:=parse_paras(true,false);
  342.                                   consume(RKLAMMER);
  343.                                end
  344.                              else
  345.                                paras:=nil;
  346.                              pd:=voiddef;
  347.                              p1 := geninlinenode(l,paras);
  348.                              do_firstpass(p1);
  349.                              statement_syssym := p1;
  350.                           end;
  351.             in_str_x_string : begin
  352.                                  consume(LKLAMMER);
  353.                                  in_args:=true;
  354.                                  paras:=parse_paras(true,false);
  355.                                  consume(RKLAMMER);
  356.                                  p1 := geninlinenode(l,paras);
  357.                                  do_firstpass(p1);
  358.                                  statement_syssym := p1;
  359.                                  pd:=voiddef;
  360.                               end;
  361.             {in_val_x :        begin
  362.                                  consume(LKLAMMER);
  363.                                  paras:=parse_paras(false);
  364.                                  consume(RKLAMMER);
  365.                                  p1 := geninlinenode(l,paras);
  366.                                  do_firstpass(p1);
  367.                                  statement_syssym := p1;
  368.                                  pd:=voiddef;
  369.                               end;    }
  370.             else internalerror(15);
  371.          end;
  372.          in_args:=prev_in_args;
  373.          Must_be_valid:=Store_valid;
  374.       end;
  375.  
  376.     { reads the parameter for a subroutine call }
  377.     procedure do_proc_call(getaddr : boolean;var again : boolean;var p1:Ptree;var pd:Pdef);
  378.  
  379.       var
  380.          prev_in_args : boolean;
  381.          prevafterassn : boolean;
  382.  
  383.       begin
  384.          prev_in_args:=in_args;
  385.          prevafterassn:=afterassignment;
  386.          afterassignment:=false;
  387.          { want we only determine the address of }
  388.          { a subroutine                          }
  389.          if not(getaddr) then
  390.            begin
  391.               if token=LKLAMMER then
  392.                 begin
  393.                    consume(LKLAMMER);
  394.                    in_args:=true;
  395.                    p1^.left:=parse_paras(false,false);
  396.                    consume(RKLAMMER);
  397.                 end
  398.               else p1^.left:=nil;
  399.  
  400.               { do firstpass because we need the  }
  401.               { result type                       }
  402.               do_firstpass(p1);
  403.            end
  404.          else
  405.            begin
  406.               { address operator @: }
  407.               p1^.left:=nil;
  408.               { forget pd }
  409.               pd:=nil;
  410.               { no postfix operators }
  411.               again:=false;
  412.            end;
  413.          pd:=p1^.resulttype;
  414.          in_args:=prev_in_args;
  415.          afterassignment:=prevafterassn;
  416.       end;
  417.  
  418.     { the ID token has to be consumed before calling this function }
  419.     procedure do_member_read(const sym : psym;var p1 : ptree;
  420.       var pd : pdef;var again : boolean);
  421.  
  422.       var
  423.          static_name : string;
  424.          paras : ptree;
  425.          oldafterassignment,isclassref : boolean;
  426.          p2 : ptree;
  427.  
  428.       begin
  429.          if sym=nil then
  430.            begin
  431.               Message(sym_e_id_no_member);
  432.               disposetree(p1);
  433.               p1:=genzeronode(errorn);
  434.               { try to clean up }
  435.               pd:=generrordef;
  436.               again:=false;
  437.            end
  438.          else
  439.            begin
  440.               isclassref:=pd^.deftype=classrefdef;
  441.               { we assume, that only procsyms and varsyms are in an object }
  442.               { symbol table, for classes, properties are allowed          }
  443.               case sym^.typ of
  444.                  procsym:
  445.                    begin
  446.                       p1:=genmethodcallnode(pprocsym(sym),srsymtable,p1);
  447.                       do_proc_call(false,again,p1,pd);
  448.                       { now we know the real method e.g. we can check for }
  449.                       { a class method                                    }
  450.                       if isclassref and ((p1^.procdefinition^.options and (poclassmethod or poconstructor))=0) then
  451.                         Message(parser_e_only_class_methods_via_class_ref);
  452.                    end;
  453.                  varsym:
  454.                    begin
  455.                       if isclassref then
  456.                         Message(parser_e_only_class_methods_via_class_ref);
  457.                       if (sym^.properties and sp_static)<>0 then
  458.                         begin
  459.                            static_name:=lowercase(srsymtable^.name^)+'_'+sym^.name;
  460.                            getsym(static_name,true);
  461.                            disposetree(p1);
  462.                            p1:=genloadnode(pvarsym(srsym),srsymtable);
  463.                         end
  464.                       else
  465.                         p1:=gensubscriptnode(pvarsym(sym),p1);
  466.                       pd:=pvarsym(sym)^.definition;
  467.                    end;
  468.                  propertysym:
  469.                    begin
  470.                       if isclassref then
  471.                         Message(parser_e_only_class_methods_via_class_ref);
  472.                       paras:=nil;
  473.                       { property parameters? }
  474.                       if token=LECKKLAMMER then
  475.                         begin
  476.                            consume(LECKKLAMMER);
  477.                            paras:=parse_paras(false,true);
  478.                            consume(RECKKLAMMER);
  479.                         end;
  480.                       { indexed property }
  481.                       if (ppropertysym(sym)^.options and ppo_indexed)<>0 then
  482.                         begin
  483.                            p2:=genordinalconstnode(ppropertysym(sym)^.index,s32bitdef);
  484.                            paras:=gencallparanode(p2,paras);
  485.                         end;
  486.                       if not(afterassignment) and not(in_args) then
  487.                         begin
  488.                            { write property: }
  489.                            { no result }
  490.                            pd:=voiddef;
  491.                            if assigned(ppropertysym(sym)^.writeaccesssym) then
  492.                              begin
  493.                                 if ppropertysym(sym)^.writeaccesssym^.typ=procsym then
  494.                                   begin
  495.                                      { generate the method call }
  496.                                      p1:=genmethodcallnode(pprocsym(
  497.                                        ppropertysym(sym)^.writeaccesssym),
  498.                                        ppropertysym(sym)^.writeaccesssym^.owner,p1);
  499.                                      p1^.left:=paras;
  500.                                      { to be on the save side }
  501.                                      oldafterassignment:=afterassignment;
  502.                                      consume(ASSIGNMENT);
  503.                                      { read the expression }
  504.                                      afterassignment:=true;
  505.                                      p2:=expr;
  506.                                      p1^.left:=gencallparanode(p2,p1^.left);
  507.                                      afterassignment:=oldafterassignment;
  508.                                   end
  509.                                 else if ppropertysym(sym)^.writeaccesssym^.typ=varsym then
  510.                                   begin
  511.                                      if assigned(paras) then
  512.                                        message(parser_e_no_paras_allowed);
  513.                                      p1:=gensubscriptnode(pvarsym(
  514.                                        ppropertysym(sym)^.readaccesssym),p1);
  515.                                      { to be on the save side }
  516.                                      oldafterassignment:=afterassignment;
  517.                                      consume(ASSIGNMENT);
  518.                                      { read the expression }
  519.                                      afterassignment:=true;
  520.                                      p2:=expr;
  521.                                      p1:=gennode(assignn,p1,p2);
  522.                                      afterassignment:=oldafterassignment;
  523.                                   end
  524.                                 else
  525.                                   begin
  526.                                      p1:=genzeronode(errorn);
  527.                                      Message(parser_e_no_procedure_to_access_property);
  528.                                   end;
  529.                              end
  530.                            else
  531.                              begin
  532.                                 p1:=genzeronode(errorn);
  533.                                 Message(parser_e_no_procedure_to_access_property);
  534.                              end;
  535.                         end
  536.                       else
  537.                         begin
  538.                            { read property: }
  539.                            pd:=ppropertysym(sym)^.proptype;
  540.                            if assigned(ppropertysym(sym)^.readaccesssym) then
  541.                              begin
  542.                                 if ppropertysym(sym)^.readaccesssym^.typ=varsym then
  543.                                   begin
  544.                                      if assigned(paras) then
  545.                                        message(parser_e_no_paras_allowed);
  546.                                      p1:=gensubscriptnode(pvarsym(
  547.                                        ppropertysym(sym)^.readaccesssym),p1);
  548.                                      pd:=pvarsym(sym)^.definition;
  549.                                   end
  550.                                 else if ppropertysym(sym)^.readaccesssym^.typ=procsym then
  551.                                   begin
  552.                                      { generate the method call }
  553.                                      p1:=genmethodcallnode(pprocsym(
  554.                                        ppropertysym(sym)^.readaccesssym),
  555.                                        ppropertysym(sym)^.readaccesssym^.owner,p1);
  556.                                      { insert paras }
  557.                                      p1^.left:=paras;
  558.                                      { if we should be delphi compatible }
  559.                                      { then force type conversion      }
  560.                                      if cs_delphi2_compatible in aktswitches then
  561.                                        p1:=gentypeconvnode(p1,pd);
  562.                                   end
  563.                                 else
  564.                                   begin
  565.                                      p1:=genzeronode(errorn);
  566.                                      Message(sym_e_type_mismatch);
  567.                                   end;
  568.                              end
  569.                            else
  570.                              begin
  571.                                 { error, no function to read property }
  572.                                 p1:=genzeronode(errorn);
  573.                                 Message(parser_e_no_procedure_to_access_property);
  574.                              end;
  575.                         end;
  576.                    end;
  577.                  else internalerror(16);
  578.               end;
  579.            end;
  580.       end;
  581.  
  582.     function factor(getaddr : boolean) : ptree;
  583.  
  584.       var
  585.          l : longint;
  586.          p1,p2,p3 : ptree;
  587.          code : word;
  588.          pd,pd2 : pdef;
  589.          unit_specific, again : boolean;
  590.          static_name : string;
  591.          sym : pvarsym;
  592.          classh : pobjectdef;
  593.          d : bestreal;
  594.          constset : pconstset;
  595.  
  596.  
  597.       { p1 and p2 must contain valid values }
  598.       procedure postfixoperators;
  599.  
  600.         begin
  601.            while again do
  602.              begin
  603.                 case token of
  604.                    CARET:
  605.                      begin
  606.                         consume(CARET);
  607.                         if pd^.deftype<>pointerdef then
  608.                           begin
  609.                              { ^ as binary operator is a problem!!!! (FK) }
  610.                              again:=false;
  611.                              Message(cg_e_invalid_qualifier);
  612.                              disposetree(p1);
  613.                              p1:=genzeronode(errorn);
  614.                           end
  615.                         else
  616.                           begin
  617.                              p1:=gensinglenode(derefn,p1);
  618.                              pd:=ppointerdef(pd)^.definition;
  619.                           end;
  620.                      end;
  621.                    LECKKLAMMER : begin
  622.                                     consume(LECKKLAMMER);
  623.                                     repeat
  624.                                       if (pd^.deftype<>arraydef) and
  625.                                          (pd^.deftype<>stringdef) and
  626.                                          (pd^.deftype<>pointerdef) then
  627.                                         begin
  628.                                            Message(cg_e_invalid_qualifier);
  629.                                            disposetree(p1);
  630.                                            p1:=genzeronode(errorn);
  631.                                         end
  632.                                       else if (pd^.deftype=pointerdef) then
  633.                                         begin
  634.                                            p2:=expr;
  635.                                            p1:=gennode(vecn,p1,p2);
  636.                                            pd:=ppointerdef(pd)^.definition;
  637.                                         end
  638.                                       else
  639.                                         begin
  640.                                            p2:=expr;
  641.                                          { support SEG:OFS for go32v2 Mem[] }
  642.                                            if (target_info.target=target_GO32V2) and
  643.                                               assigned(p1^.symtableentry) and
  644.                                               assigned(p1^.symtableentry^.owner^.name) and
  645.                                               (p1^.symtableentry^.owner^.name^='SYSTEM') and
  646.                                               ((p1^.symtableentry^.name='MEM') or
  647.                                                (p1^.symtableentry^.name='MEMW') or
  648.                                                (p1^.symtableentry^.name='MEML')) then
  649.                                              begin
  650.                                                if (token=COLON) then
  651.                                                 begin
  652.                                                   consume(COLON);
  653.                                                   p3:=gennode(muln,genordinalconstnode($10,s32bitdef),p2);
  654.                                                   p2:=expr;
  655.                                                   p2:=gennode(addn,p2,p3);
  656.                                                   p1:=gennode(vecn,p1,p2);
  657.                                                   p1^.memseg:=true;
  658.                                                   p1^.memindex:=true;
  659.                                                 end
  660.                                                else
  661.                                                 begin
  662.                                                   p1:=gennode(vecn,p1,p2);
  663.                                                   p1^.memindex:=true;
  664.                                                 end;
  665.                                              end
  666.                                            else
  667.                                              p1:=gennode(vecn,p1,p2);
  668.                                            if pd^.deftype=stringdef then
  669.                                              pd:=cchardef
  670.                                            else
  671.                                              pd:=parraydef(pd)^.definition;
  672.                                         end;
  673.                                       if token=COMMA then consume(COMMA)
  674.                                         else break;
  675.                                     until false;
  676.                                     consume(RECKKLAMMER);
  677.                                  end;
  678.                    POINT       : begin
  679.                                     consume(POINT);
  680.                                     case pd^.deftype of
  681.                                        recorddef:
  682.                                              begin
  683.                                                 sym:=pvarsym(precdef(pd)^.symtable^.search(pattern));
  684.                                                 consume(ID);
  685.                                                 if sym=nil then
  686.                                                   begin
  687.                                                      Message(sym_e_illegal_field);
  688.                                                      disposetree(p1);
  689.                                                      p1:=genzeronode(errorn);
  690.                                                   end
  691.                                                 else
  692.                                                   begin
  693.                                                      p1:=gensubscriptnode(sym,p1);
  694.                                                      pd:=sym^.definition;
  695.                                                   end;
  696.                                              end;
  697.                                        classrefdef:
  698.                                          begin
  699.                                             classh:=pobjectdef(pclassrefdef(pd)^.definition);
  700.                                             sym:=nil;
  701.                                             while assigned(classh) do
  702.                                               begin
  703.                                                  sym:=pvarsym(classh^.publicsyms^.search(pattern));
  704.                                                  srsymtable:=classh^.publicsyms;
  705.                                                  if assigned(sym) then
  706.                                                    break;
  707.                                                  classh:=classh^.childof;
  708.                                               end;
  709.                                             consume(ID);
  710.                                             do_member_read(sym,p1,pd,again);
  711.                                          end;
  712.                                        objectdef:
  713.                                              begin
  714.                                                 classh:=pobjectdef(pd);
  715.                                                 sym:=nil;
  716.                                                 while assigned(classh) do
  717.                                                   begin
  718.                                                      sym:=pvarsym(classh^.publicsyms^.search(pattern));
  719.                                                      srsymtable:=classh^.publicsyms;
  720.                                                      if assigned(sym) then
  721.                                                        break;
  722.                                                      classh:=classh^.childof;
  723.                                                   end;
  724.                                                 consume(ID);
  725.                                                 do_member_read(sym,p1,pd,again);
  726.                                              end;
  727.                                        pointerdef:
  728.                                           begin
  729.                                              if ppointerdef(pd)^.definition^.deftype
  730.                                                 in [recorddef,objectdef,classrefdef] then
  731.                                                 begin
  732.                                                    Message(cg_e_invalid_qualifier);
  733.                                                    { exterror:=strpnew(' may be pointer deref ^ is missing');
  734.                                                    error(invalid_qualifizier); }
  735.                                                    Comment(V_hint,' may be pointer deref ^ is missing');
  736.                                                 end
  737.                                              else
  738.                                                 Message(cg_e_invalid_qualifier);
  739.                                           end
  740.                                           else
  741.                                              begin
  742.                                                 Message(cg_e_invalid_qualifier);
  743.                                                 disposetree(p1);
  744.                                                 p1:=genzeronode(errorn);
  745.                                              end;
  746.                                     end;
  747.                                  end;
  748.                    else
  749.                      begin
  750.                         { is this a procedure variable ? }
  751.                         if assigned(pd) then
  752.                         begin
  753.                           if  (pd^.deftype=procvardef) then
  754.                           begin
  755.                              if getprocvar then
  756.                                again:=false
  757.                              else
  758.                              if (token=LKLAMMER) or
  759.                                 ((pprocvardef(pd)^.para1=nil) and
  760.                                 (token<>ASSIGNMENT) and (not in_args)) then
  761.                                begin
  762.                                   { do this in a strange way  }
  763.                                   { it's not a clean solution }
  764.                                   p2:=p1;
  765.                                   p1:=gencallnode(nil,
  766.                                     nil);
  767.                                   p1^.right:=p2;
  768.                                   p1^.unit_specific:=unit_specific;
  769.                                   if token=LKLAMMER then
  770.                                     begin
  771.                                        consume(LKLAMMER);
  772.                                        p1^.left:=parse_paras(false,false);
  773.                                        consume(RKLAMMER);
  774.                                     end;
  775.                                   pd:=pprocvardef(pd)^.retdef;
  776.                                   p1^.resulttype:=pd;
  777.                                end
  778.                              else again:=false;
  779.                              p1^.resulttype:=pd;
  780.                           end
  781.                           else again:=false;
  782.                         end
  783.                         else again:=false;
  784.                      end;
  785.                 end;
  786.            end;
  787.       end;
  788.  
  789.     procedure do_set(p : pconstset;pos : longint);
  790.  
  791.       var
  792.          l : longint;
  793.  
  794.       begin
  795.          if (pos>255) or
  796.             (pos<0) then
  797.            Message(parser_e_illegal_set_expr);
  798.          l:=pos div 8;
  799.          { do we allow the same twice }
  800.          if (p^[l] and (1 shl (pos mod 8)))<>0 then
  801.            Message(parser_e_illegal_set_expr);
  802.          p^[l]:=p^[l] or (1 shl (pos mod 8));
  803.       end;
  804.  
  805.       var
  806.          possible_error : boolean;
  807.          storesymtablestack : psymtable;
  808.          actprocsym : pprocsym;
  809.  
  810.       begin
  811.          case token of
  812.             ID:
  813.           begin
  814.                  { allow post fix operators }
  815.                  again:=true;
  816.                  if (cs_delphi2_compatible in aktswitches) and
  817.                     (pattern='RESULT') and
  818.                    assigned(aktprocsym) and
  819.                    (procinfo.retdef<>pdef(voiddef)) then
  820.                    begin
  821.                       consume(ID);
  822.                       p1:=genzeronode(funcretn);
  823.                       pd:=procinfo.retdef;
  824. {$ifdef TEST_FUNCRET}
  825.                       p1^.funcretprocinfo:=pointer(@procinfo);
  826.                       p1^.retdef:=pd;
  827. {$endif TEST_FUNCRET}
  828.                    end
  829.                  else
  830.                    begin
  831.                       getsym(pattern,true);
  832.                       consume(ID);
  833.                       { is this an access to a function result ? }
  834.                        if assigned(aktprocsym) and
  835.                         ((srsym^.name=aktprocsym^.name) or
  836.                         ((pvarsym(srsym)=opsym) and
  837.                         ((pprocdef(aktprocsym^.definition)^.options and pooperator)<>0))) and
  838.                         (procinfo.retdef<>pdef(voiddef)) and
  839.                         (token<>LKLAMMER) and
  840.                         (not ((cs_tp_compatible in aktswitches) and
  841.                         (afterassignment or in_args))) then
  842.                         begin
  843.                            p1:=genzeronode(funcretn);
  844.                            pd:=procinfo.retdef;
  845. {$ifdef TEST_FUNCRET}
  846.                            p1^.funcretprocinfo:=pointer(@procinfo);
  847.                            p1^.retdef:=pd;
  848. {$endif TEST_FUNCRET}
  849.                         end
  850.                       else
  851.                         { else it's a normal symbol }
  852.                         begin
  853.                            if srsym^.typ=unitsym then
  854.                              begin
  855.                                 consume(POINT);
  856.                                 getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  857.                                 unit_specific:=true;
  858.                                 consume(ID);
  859.                              end
  860.                            else
  861.                              unit_specific:=false;
  862.  
  863.                            if not assigned(srsym) then
  864.                              Begin
  865.                                 p1:=genzeronode(errorn);
  866.                                 { try to clean up }
  867.                                 pd:=generrordef;
  868.                              end
  869.                            else
  870.                            case srsym^.typ of
  871.                               absolutesym:
  872.                                 begin
  873.                                    p1:=genloadnode(pvarsym(srsym),srsymtable);
  874.                                    pd:=pabsolutesym(srsym)^.definition;
  875.                                 end;
  876.                               varsym:
  877.                                 begin
  878.                                    { are we in a class method ? }
  879.                                    if (srsymtable^.symtabletype=objectsymtable) and
  880.                                      assigned(aktprocsym) and
  881.                                      ((aktprocsym^.definition^.options and poclassmethod)<>0) then
  882.                                      Message(parser_e_only_class_methods);
  883.  
  884.                                      if (srsym^.properties and sp_static)<>0 then
  885.                                        begin
  886.                                           static_name:=lowercase(srsymtable^.name^)+'_'+srsym^.name;
  887.                                           getsym(static_name,true);
  888.                                        end;
  889.                                      p1:=genloadnode(pvarsym(srsym),srsymtable);
  890.                                      if pvarsym(srsym)^.is_valid=0 then
  891.                                        begin
  892.                                           p1^.is_first := true;
  893.                                           { set special between first loaded
  894.                                             until checked in firstpass }
  895.                                           pvarsym(srsym)^.is_valid:=2;
  896.                                        end;
  897.                                      pd:=pvarsym(srsym)^.definition;
  898.                                   end;
  899.                               typedconstsym:
  900.                                 begin
  901.                                    p1:=gentypedconstloadnode(ptypedconstsym(srsym),srsymtable);
  902.                                    pd:=ptypedconstsym(srsym)^.definition;
  903.                                 end;
  904.                               syssym:
  905.                                 p1:=statement_syssym(psyssym(srsym)^.number,pd);
  906.                               typesym:
  907.                                 begin
  908.                                    pd:=ptypesym(srsym)^.definition;
  909.                                    if token=LKLAMMER then
  910.                                      begin
  911.                                         consume(LKLAMMER);
  912.                                         p1:=expr;
  913.                                         consume(RKLAMMER);
  914.                                         p1:=gentypeconvnode(p1,pd);
  915.                                         p1^.explizit:=true;
  916.                                      end
  917.                                    else if (token=POINT) and
  918.                                      (pd^.deftype=objectdef) and
  919.                                      ((pobjectdef(pd)^.options and oois_class)=0) then
  920.                                      begin
  921.                                         consume(POINT);
  922.                                         if assigned(procinfo._class) then
  923.                                           begin
  924.                                              if procinfo._class^.isrelated(pobjectdef(pd)) then
  925.                                                begin
  926.                                                   p1:=genzeronode(typen);
  927.                                                   p1^.resulttype:=pd;
  928.                                                   srsymtable:=pobjectdef(pd)^.publicsyms;
  929.                                                   sym:=pvarsym(srsymtable^.search(pattern));
  930.                                                   consume(ID);
  931.                                                   do_member_read(sym,p1,pd,again);
  932.                                                end
  933.                                              else
  934.                                                begin
  935.                                                   Message(parser_e_no_super_class);
  936.                                                   pd:=generrordef;
  937.                                                   again:=false;
  938.                                                end;
  939.                                           end
  940.                                         else
  941.                                           begin
  942.                                              { allows @TObject.Load }
  943.                                              { also allows static methods and variables }
  944.  
  945.                                               p1:=genzeronode(typen);
  946.                                               p1^.resulttype:=pd;
  947.                                               srsymtable:=pobjectdef(pd)^.publicsyms;
  948.                                               sym:=pvarsym(srsymtable^.search(pattern));
  949.                                               if not(getaddr) and
  950.                                                 ((sym^.properties and sp_static)=0) then
  951.                                                 Message(sym_e_only_static_in_static)
  952.                                               else
  953.                                                 begin
  954.                                                    consume(ID);
  955.                                                    do_member_read(sym,p1,pd,again);
  956.                                                 end;
  957.                                           end
  958.                                      end
  959.                                    else
  960.                                      begin
  961.                                         { class reference ? }
  962.                                         if (pd^.deftype=objectdef)
  963.                                           and ((pobjectdef(pd)^.options and oois_class)<>0) then
  964.                                           begin
  965.                                              p1:=genzeronode(typen);
  966.                                              p1^.resulttype:=pd;
  967.                                              pd:=new(pclassrefdef,init(pd));
  968.                                              p1:=gensinglenode(loadvmtn,p1);
  969.                                              p1^.resulttype:=pd;
  970.                                           end
  971.                                         else
  972.                                           begin
  973.                                              { generate a type node }
  974.                                              { (for typeof etc)     }
  975.                                              p1:=genzeronode(typen);
  976.                                              p1^.resulttype:=pd;
  977.                                              pd:=voiddef;
  978.                                           end;
  979.                                      end;
  980.                                 end;
  981.                               enumsym:
  982.                                 begin
  983.                                    p1:=genenumnode(penumsym(srsym));
  984.                                    pd:=p1^.resulttype;
  985.                                 end;
  986.                               constsym:
  987.                                 begin
  988.                                    case pconstsym(srsym)^.consttype of
  989.                                       constint:
  990.                                         p1:=genordinalconstnode(pconstsym(srsym)^.value,s32bitdef);
  991.                                       conststring:
  992.                                         p1:=genstringconstnode(pstring(pconstsym(srsym)^.value)^);
  993.                                       constchar:
  994.                                         p1:=genordinalconstnode(pconstsym(srsym)^.value,cchardef);
  995.                                       constreal:
  996.                                         p1:=genrealconstnode(pdouble(pconstsym(srsym)^.value)^);
  997.                                       constbool:
  998.                                         p1:=genordinalconstnode(pconstsym(srsym)^.value,booldef);
  999.                                       constseta:
  1000.                                         p1:=gensetconstruktnode(pconstset(pconstsym(srsym)^.value),
  1001.                                           psetdef(pconstsym(srsym)^.definition));
  1002.                                       constord:
  1003.                                         p1:=genordinalconstnode(pconstsym(srsym)^.value,
  1004.                                           pconstsym(srsym)^.definition);
  1005.                                    end;
  1006.                                    pd:=p1^.resulttype;
  1007.                                 end;
  1008.                               procsym:
  1009.                                 begin
  1010.                                    { are we in a class method ? }
  1011.                                    possible_error:=(srsymtable^.symtabletype=objectsymtable) and
  1012.                                      assigned(aktprocsym) and
  1013.                                      ((aktprocsym^.definition^.options and poclassmethod)<>0);
  1014.                                    p1:=gencallnode(pprocsym(srsym),srsymtable);
  1015.                                    p1^.unit_specific:=unit_specific;
  1016.                                    do_proc_call(getaddr,again,p1,pd);
  1017.                                    if possible_error and
  1018.                                      ((p1^.procdefinition^.options and poclassmethod)=0) then
  1019.                                      Message(parser_e_only_class_methods);
  1020.                                 end;
  1021.                               propertysym:
  1022.                                 begin
  1023.                                    { access to property in a method }
  1024.  
  1025.                                    { are we in a class method ? }
  1026.                                    if (srsymtable^.symtabletype=objectsymtable) and
  1027.                                      assigned(aktprocsym) and
  1028.                                      ((aktprocsym^.definition^.options and poclassmethod)<>0) then
  1029.                                      Message(parser_e_only_class_methods);
  1030.                                    { !!!!! }
  1031.                                 end;
  1032.                               errorsym:
  1033.                                 begin
  1034.                                    p1:=genzeronode(errorn);
  1035.                                    pd:=generrordef;
  1036.                                    if token=LKLAMMER then
  1037.                                      begin
  1038.                                         consume(LKLAMMER);
  1039.                                         parse_paras(false,false);
  1040.                                         consume(RKLAMMER);
  1041.                                      end;
  1042.                                 end;
  1043.                               else
  1044.                                 begin
  1045.                                    p1:=genzeronode(errorn);
  1046.                                    pd:=generrordef;
  1047.                                    Message(cg_e_illegal_expression);
  1048.                                 end;
  1049.                            end; { end case }
  1050.                         end;
  1051.                    end;
  1052.                  { handle post fix operators }
  1053.                  postfixoperators;
  1054.               end;
  1055.             _NEW : begin
  1056.                       consume(_NEW);
  1057.                       consume(LKLAMMER);
  1058.                       p1:=factor(false);
  1059.                       if p1^.treetype<>typen then
  1060.                         Message(sym_e_type_id_expected);
  1061.                       pd:=p1^.resulttype;
  1062.                       pd2:=pd;
  1063.                       if (pd^.deftype<>pointerdef) or
  1064.                          (ppointerdef(pd)^.definition^.deftype<>objectdef) then
  1065.                         begin
  1066.                            Message(parser_e_pointer_to_class_expected);
  1067.  
  1068.                            { if an error occurs, read til the end of the new }
  1069.                            { statement                                       }
  1070.                            p1:=genzeronode(errorn);
  1071.                            l:=1;
  1072.                            while true do
  1073.                              begin
  1074.                                 case token of
  1075.                                    LKLAMMER : inc(l);
  1076.                                    RKLAMMER : dec(l);
  1077.                                 end;
  1078.                                 consume(token);
  1079.                                 if l=0 then
  1080.                                   break;
  1081.                              end;
  1082.                         end
  1083.                       else
  1084.                         begin
  1085.                            disposetree(p1);
  1086.                            p1:=genzeronode(hnewn);
  1087.                            p1^.resulttype:=ppointerdef(pd)^.definition;
  1088.                            consume(COMMA);
  1089.  
  1090.                            afterassignment:=false;
  1091.                            { determines the current object defintion }
  1092.                            classh:=pobjectdef(ppointerdef(pd)^.definition);
  1093.  
  1094.                            { check for an abstract class }
  1095.                            if (classh^.options and oois_abstract)<>0 then
  1096.                              Message(sym_e_no_instance_of_abstract_object);
  1097.  
  1098.                            { search the constructor also in the symbol tables of }
  1099.                            { the parents                                          }
  1100.  
  1101.                            { no constructor found }
  1102.                            sym:=nil;
  1103.                            while assigned(classh) do
  1104.                              begin
  1105.                                 sym:=pvarsym(classh^.publicsyms^.search(pattern));
  1106.                                 srsymtable:=classh^.publicsyms;
  1107.                                 if assigned(sym) then
  1108.                                   break;
  1109.                                 classh:=classh^.childof;
  1110.                              end;
  1111.  
  1112.                            consume(ID);
  1113.                            do_member_read(sym,p1,pd,again);
  1114.                            if (p1^.treetype<>calln) or
  1115.                               (assigned(p1^.procdefinition) and
  1116.                                ((p1^.procdefinition^.options and poconstructor)=0)) then
  1117.                              Message(parser_e_expr_have_to_be_constructor_call);
  1118.                            p1:=gensinglenode(newn,p1);
  1119.  
  1120.                            { set the resulttype }
  1121.                            p1^.resulttype:=pd2;
  1122.                            consume(RKLAMMER);
  1123.                         end;
  1124.                    end;
  1125.             _SELF:
  1126.               begin
  1127.                  again:=true;
  1128.                  consume(_SELF);
  1129.                  if not assigned(procinfo._class) then
  1130.                    begin
  1131.                       p1:=genzeronode(errorn);
  1132.                       pd:=generrordef;
  1133.                       again:=false;
  1134.                       Message(parser_e_self_not_in_method);
  1135.                    end
  1136.                  else
  1137.                    begin
  1138.                       if (aktprocsym^.definition^.options and poclassmethod)<>0 then
  1139.                         begin
  1140.                            { self in class methods is a class reference type }
  1141.                            pd:=new(pclassrefdef,init(procinfo._class));
  1142.                            p1:=genselfnode(pd);
  1143.                            p1^.resulttype:=pd;
  1144.                         end
  1145.                       else
  1146.                         begin
  1147.                            p1:=genselfnode(procinfo._class);
  1148.                            p1^.resulttype:=procinfo._class;
  1149.                         end;
  1150.                       pd:=p1^.resulttype;
  1151.                       postfixoperators;
  1152.                    end;
  1153.               end;
  1154.             _INHERITED : begin
  1155.                             again:=true;
  1156.                             consume(_INHERITED);
  1157.                             if assigned(procinfo._class) then
  1158.                               begin
  1159.                                  classh:=procinfo._class^.childof;
  1160.                                  while assigned(classh) do
  1161.                                    begin
  1162.                                       srsymtable:=pobjectdef(classh)^.publicsyms;
  1163.                                       sym:=pvarsym(srsymtable^.search(pattern));
  1164.                                       if assigned(sym) then
  1165.                                         begin
  1166.                                            p1:=genzeronode(typen);
  1167.                                            p1^.resulttype:=classh;
  1168.                                            pd:=p1^.resulttype;
  1169.                                            consume(ID);
  1170.                                            do_member_read(sym,p1,pd,again);
  1171.                                            break;
  1172.                                         end;
  1173.                                       classh:=classh^.childof;
  1174.                                    end;
  1175.                                  if classh=nil then
  1176.                                    begin
  1177.                                       Message1(sym_e_id_no_member,pattern);
  1178.                                       again:=false;
  1179.                                       pd:=generrordef;
  1180.                                       p1:=genzeronode(errorn);
  1181.                                    end;
  1182.                               end
  1183.                             else
  1184.                               Message(parser_e_generic_methods_only_in_methods);
  1185.                             postfixoperators;
  1186.                          end;
  1187.             INTCONST : begin
  1188.                           valint(pattern,l,code);
  1189.                           if code<>0 then
  1190.                             begin
  1191.                                val(pattern,d,code);
  1192.                                if code<>0 then
  1193.                                  begin
  1194.                                     Message(cg_e_invalid_integer);
  1195.                                     l:=1;
  1196.                                     consume(INTCONST);
  1197.                                     p1:=genordinalconstnode(l,s32bitdef);
  1198.                                  end
  1199.                                else
  1200.                                  begin
  1201.                                     consume(INTCONST);
  1202.                                     p1:=genrealconstnode(d);
  1203.                                  end;
  1204.                             end
  1205.                           else
  1206.                             begin
  1207.                                consume(INTCONST);
  1208.                                p1:=genordinalconstnode(l,s32bitdef);
  1209.                             end;
  1210.                        end;
  1211.             REALNUMBER : begin
  1212.                           val(pattern,d,code);
  1213.                           if code<>0 then
  1214.                             begin
  1215.                                Message(parser_e_error_in_real);
  1216.                                d:=1.0;
  1217.                             end;
  1218.                           consume(REALNUMBER);
  1219.                           p1:=genrealconstnode(d);
  1220.                         end;
  1221.             { FILE and STRING can be also a type cast }
  1222.             _STRING:
  1223.               begin
  1224.                  pd:=stringtype;
  1225.                  consume(LKLAMMER);
  1226.                  p1:=expr;
  1227.                  consume(RKLAMMER);
  1228.                  p1:=gentypeconvnode(p1,pd);
  1229.                  p1^.explizit:=true;
  1230.                  { handle postfix operators here e.g. string(a)[10] }
  1231.                  again:=true;
  1232.                  postfixoperators;
  1233.               end;
  1234.             _FILE:
  1235.               begin
  1236.                  pd:=cfiledef;
  1237.                  consume(_FILE);
  1238.                  consume(LKLAMMER);
  1239.                  p1:=expr;
  1240.                  consume(RKLAMMER);
  1241.                  p1:=gentypeconvnode(p1,pd);
  1242.                  p1^.explizit:=true;
  1243.                  { handle postfix operators here e.g. string(a)[10] }
  1244.                  again:=true;
  1245.                  postfixoperators;
  1246.               end;
  1247.             CSTRING:
  1248.               begin
  1249.                  p1:=genstringconstnode(pattern);
  1250.                  consume(CSTRING);
  1251.               end;
  1252.             CCHAR:
  1253.               begin
  1254.                  p1:=genordinalconstnode(ord(pattern[1]),cchardef);
  1255.                  consume(CCHAR);
  1256.               end;
  1257.             KLAMMERAFFE : begin
  1258.                              consume(KLAMMERAFFE);
  1259.                              p1:=factor(true);
  1260.                              p1:=gensinglenode(addrn,p1);
  1261.                           end;
  1262.             LKLAMMER : begin
  1263.                           consume(LKLAMMER);
  1264.                           p1:=expr;
  1265.                           consume(RKLAMMER);
  1266.                           { it's not a good solution        }
  1267.                           { but (a+b)^ makes some problems  }
  1268.                           case token of
  1269.                              CARET,POINT,LECKKLAMMER:
  1270.                                begin
  1271.                                   { we need the resulttype  }
  1272.                                   { of the expression in pd }
  1273.                                   do_firstpass(p1);
  1274.                                   pd:=p1^.resulttype;
  1275.  
  1276.                                   again:=true;
  1277.                                   postfixoperators;
  1278.                                end;
  1279.                           end;
  1280.                        end;
  1281.             LECKKLAMMER : begin
  1282.                              consume(LECKKLAMMER);
  1283.                              new(constset);
  1284.                              for l:=0 to 31 do
  1285.                                constset^[l]:=0;
  1286.                              p2:=nil;
  1287.                              pd:=nil;
  1288.                              if token<>RECKKLAMMER then
  1289.                                while true do
  1290.                                  begin
  1291.                                     p1:=expr;
  1292.                                     do_firstpass(p1);
  1293.                                     case p1^.treetype of
  1294.                                        ordconstn : begin
  1295.                                                       if pd=nil then
  1296.                                                         pd:=p1^.resulttype;
  1297.                                                      if not(is_equal(pd,p1^.resulttype)) then
  1298.                                                        Message(parser_e_typeconflict_in_set)
  1299.                                                      else
  1300.                                                        do_set(constset,p1^.value);
  1301.                                                      disposetree(p1);
  1302.                                                    end;
  1303.                                        rangen : begin
  1304.                                                    if pd=nil then
  1305.                                                      pd:=p1^.left^.resulttype;
  1306.                                                    if not(is_equal(pd,p1^.left^.resulttype)) then
  1307.                                                      Message(parser_e_typeconflict_in_set)
  1308.                                                    else
  1309.                                                      for l:=p1^.left^.value to p1^.right^.value do
  1310.                                                        do_set(constset,l);
  1311.                                                    disposetree(p1);
  1312.                                                 end;
  1313.                                        stringconstn : begin
  1314.                                                          if pd=nil then
  1315.                                                            pd:=cchardef;
  1316.                                                    if not(is_equal(pd,cchardef)) then
  1317.                                                      Message(parser_e_typeconflict_in_set)
  1318.                                                    else
  1319.                                                      for l:=1 to length(pstring(p1^.values)^) do
  1320.                                                        do_set(constset,ord(pstring(p1^.values)^[l]));
  1321.                                                    disposetree(p1);
  1322.                                                 end;
  1323.                                        else
  1324.                                           begin
  1325.                                              if pd=nil then
  1326.                                                pd:=p1^.resulttype;
  1327.                                              if not(is_equal(pd,p1^.resulttype)) then
  1328.                                                Message(parser_e_typeconflict_in_set);
  1329.                                              p2:=gennode(setelen,p1,p2);
  1330.                                           end;
  1331.                                     end;
  1332.                                     if token=COMMA then
  1333.                                       consume(COMMA)
  1334.                                     else break;
  1335.                                  end;
  1336.                              consume(RECKKLAMMER);
  1337.                              p1:=gensinglenode(setconstrn,p2);
  1338.                              p1^.resulttype:=new(psetdef,init(pd,255));
  1339.                              p1^.constset:=constset;
  1340.                           end;
  1341.             PLUS     : begin
  1342.                           consume(PLUS);
  1343.                           p1:=factor(false);
  1344.                        end;
  1345.             MINUS    : begin
  1346.                           consume(MINUS);
  1347.                           p1:=factor(false);
  1348.                           p1:=gensinglenode(umminusn,p1);
  1349.                        end;
  1350.             _NOT     : begin
  1351.                           consume(_NOT);
  1352.                           p1:=factor(false);
  1353.                           p1:=gensinglenode(notn,p1);
  1354.                        end;
  1355.             _TRUE    : begin
  1356.                           consume(_TRUE);
  1357.                           p1:=genordinalconstnode(1,booldef);
  1358.                        end;
  1359.             _FALSE    : begin
  1360.                           consume(_FALSE);
  1361.                           p1:=genordinalconstnode(0,booldef);
  1362.                        end;
  1363.             _NIL      : begin
  1364.                            consume(_NIL);
  1365.                            p1:=genzeronode(niln);
  1366.                         end;
  1367.             else
  1368.               begin
  1369.                  p1:=genzeronode(errorn);
  1370.                  consume(token);
  1371.                  Message(cg_e_illegal_expression);
  1372.               end;
  1373.          end;
  1374.          factor:=p1;
  1375.       end;
  1376.  
  1377.     type    Toperator_precedence=(opcompare,opaddition,opmultiply);
  1378.  
  1379.     const   tok2node:array[PLUS.._XOR] of Ttreetyp=
  1380.                     (addn,subn,muln,slashn,equaln,gtn,ltn,gten,lten,
  1381.                      isn,asn,inn,
  1382.                      nothingn,caretn,nothingn,unequaln,nothingn,
  1383.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1384.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1385.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1386.                      nothingn,andn,nothingn,nothingn,nothingn,
  1387.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1388.                      nothingn,nothingn,divn,nothingn,nothingn,
  1389.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1390.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1391.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1392.                      modn,nothingn,nothingn,nothingn,nothingn,
  1393.                      nothingn,nothingn,orn,
  1394.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1395.                      nothingn,nothingn,shln,shrn,
  1396.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1397.                      nothingn,nothingn,nothingn,nothingn,nothingn,
  1398.                      nothingn,xorn);
  1399.             operator_levels:array[Toperator_precedence] of set of Ttoken=
  1400.                     ([LT,LTE,GT,GTE,EQUAL,UNEQUAL,_IN,_IS],
  1401.                      [PLUS,MINUS,_OR,_XOR],
  1402.                      [CARET,SYMDIF,STAR,SLASH,_DIV,_MOD,_AND,_SHL,_SHR,_AS]);
  1403.  
  1404.     function sub_expr(pred_level:Toperator_precedence):Ptree;
  1405.  
  1406.     {Reads a subexpression while the operators are of the current precedence
  1407.      level, or any higher level. Replaces the old term, simpl_expr and
  1408.      simpl2_expr.}
  1409.  
  1410.     var p1,p2:Ptree;
  1411.         oldt:Ttoken;
  1412.  
  1413.     begin
  1414. {        if pred_level=high(Toperator_precedence) then }
  1415.          if pred_level=opmultiply then
  1416.             p1:=factor(getprocvar)
  1417.         else
  1418.             p1:=sub_expr(succ(pred_level));
  1419.         repeat
  1420.             if token in operator_levels[pred_level] then
  1421.                 begin
  1422.                     oldt:=token;
  1423.                     consume(token);
  1424. {                    if pred_level=high(Toperator_precedence) then }
  1425.                     if pred_level=opmultiply then
  1426.                         p2:=factor(getprocvar)
  1427.                     else
  1428.                         p2:=sub_expr(succ(pred_level));
  1429.                     p1:=gennode(tok2node[oldt],p1,p2);
  1430.                 end
  1431.             else
  1432.                 break;
  1433.         until false;
  1434.         sub_expr:=p1;
  1435.     end;
  1436.  
  1437.     function expr : ptree;
  1438.  
  1439.       var
  1440.          p1,p2 : ptree;
  1441.          oldafterassignment : boolean;
  1442.  
  1443.       begin
  1444.          oldafterassignment:=afterassignment;
  1445.          p1:=sub_expr(opcompare);
  1446.          if token in [ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  1447.            afterassignment:=true;
  1448.          case token of
  1449.             POINTPOINT : begin
  1450.                             consume(POINTPOINT);
  1451.                             p2:=sub_expr(opcompare);
  1452.                             p1:=gennode(rangen,p1,p2);
  1453.                          end;
  1454.             ASSIGNMENT : begin
  1455.                             consume(ASSIGNMENT);
  1456.                             { avoid a firstpass of a procedure if
  1457.                             it must be assigned to a procvar }
  1458.                             { should be recursive for a:=b:=c !!! }
  1459.                             if (p1^.resulttype<>nil) and (p1^.resulttype^.deftype=procvardef) then
  1460.                               getprocvar:=true;
  1461.                             p2:=sub_expr(opcompare);
  1462.                             if getprocvar and (p2^.treetype=calln) then
  1463.                               begin
  1464.                                  p2^.treetype:=loadn;
  1465.                                  p2^.resulttype:=pprocsym(p2^.symtableprocentry)^.definition;
  1466.                                  p2^.symtableentry:=p2^.symtableprocentry;
  1467.                               end;
  1468.                             getprocvar:=false;
  1469.                             p1:=gennode(assignn,p1,p2);
  1470.                          end;
  1471.                          { this is the code for C like assignements }
  1472.                          { from an improvement of Peter Schaefer    }
  1473.             _PLUSASN   : begin
  1474.                             consume(_PLUSASN  );
  1475.                             p2:=sub_expr(opcompare);
  1476.                             p1:=gennode(assignn,p1,gennode(addn,getcopy(p1),p2));
  1477.                             { was first
  1478.                               p1:=gennode(assignn,p1,gennode(addn,p1,p2));
  1479.                               but disposetree assumes that we have a real
  1480.                               *** tree *** }
  1481.                          end;
  1482.  
  1483.             _MINUSASN   : begin
  1484.                             consume(_MINUSASN  );
  1485.                             p2:=sub_expr(opcompare);
  1486.                             p1:=gennode(assignn,p1,gennode(subn,getcopy(p1),p2));
  1487.                          end;
  1488.             _STARASN   : begin
  1489.                             consume(_STARASN  );
  1490.                             p2:=sub_expr(opcompare);
  1491.                             p1:=gennode(assignn,p1,gennode(muln,getcopy(p1),p2));
  1492.                          end;
  1493.             _SLASHASN   : begin
  1494.                             consume(_SLASHASN  );
  1495.                             p2:=sub_expr(opcompare);
  1496.                             p1:=gennode(assignn,p1,gennode(slashn,getcopy(p1),p2));
  1497.                          end;
  1498.          end;
  1499.          afterassignment:=oldafterassignment;
  1500.          expr:=p1;
  1501.       end;
  1502.  
  1503.     function get_intconst:longint;
  1504.  
  1505.     {Reads an expression, tries to evalute it and check if it is an integer
  1506.      constant. Then the constant is returned.}
  1507.  
  1508.     var p:Ptree;
  1509.  
  1510.     begin
  1511.         p:=expr;
  1512.         do_firstpass(p);
  1513.         if (p^.treetype<>ordconstn) and
  1514.          (p^.resulttype^.deftype=orddef) and
  1515.          not (Porddef(p^.resulttype)^.typ in
  1516.          [uvoid,uchar,bool8bit]) then
  1517.             Message(cg_e_illegal_expression)
  1518.         else
  1519.             get_intconst:=p^.value;
  1520.         disposetree(p);
  1521.     end;
  1522.  
  1523.     function get_stringconst:string;
  1524.  
  1525.     {Reads an expression, tries to evaluate it and checks if it is a string
  1526.      constant. Then the constant is returned.}
  1527.  
  1528.     var p:Ptree;
  1529.  
  1530.     begin
  1531.         get_stringconst:='';
  1532.         p:=expr;
  1533.         do_firstpass(p);
  1534.         if p^.treetype<>stringconstn then
  1535.             if (p^.treetype=ordconstn) and
  1536.              (p^.resulttype^.deftype=orddef) and
  1537.              (Porddef(p^.resulttype)^.typ=uchar) then
  1538.                 get_stringconst:=char(p^.value)
  1539.             else
  1540.                 Message(cg_e_illegal_expression)
  1541.         else
  1542.             get_stringconst:=p^.values^;
  1543.         disposetree(p);
  1544.     end;
  1545.  
  1546. end.
  1547. {
  1548.   $Log: pexpr.pas,v $
  1549.   Revision 1.2.2.1  1998/05/21 12:26:55  carl
  1550.     * crash bugfix
  1551.  
  1552.   Revision 1.2  1998/03/26 11:18:31  florian
  1553.     - switch -Sa removed
  1554.     - support of a:=b:=0 removed
  1555.  
  1556.   Revision 1.1.1.1  1998/03/25 11:18:14  root
  1557.   * Restored version
  1558.  
  1559.   Revision 1.26  1998/03/24 21:48:33  florian
  1560.     * just a couple of fixes applied:
  1561.          - problem with fixed16 solved
  1562.          - internalerror 10005 problem fixed
  1563.          - patch for assembler reading
  1564.          - small optimizer fix
  1565.          - mem is now supported
  1566.  
  1567.   Revision 1.25  1998/03/21 23:59:39  florian
  1568.     * indexed properties fixed
  1569.     * ppu i/o of properties fixed
  1570.     * field can be also used for write access
  1571.     * overriding of properties
  1572.  
  1573.   Revision 1.24  1998/03/16 22:42:21  florian
  1574.     * some fixes of Peter applied:
  1575.       ofs problem, profiler support
  1576.  
  1577.   Revision 1.23  1998/03/11 11:23:57  florian
  1578.     * bug0081 and bug0109 fixed
  1579.  
  1580.   Revision 1.22  1998/03/10 16:27:42  pierre
  1581.     * better line info in stabs debug
  1582.     * symtabletype and lexlevel separated into two fields of tsymtable
  1583.     + ifdef MAKELIB for direct library output, not complete
  1584.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  1585.       working
  1586.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  1587.       working
  1588.  
  1589.   Revision 1.21  1998/03/10 01:17:24  peter
  1590.     * all files have the same header
  1591.     * messages are fully implemented, EXTDEBUG uses Comment()
  1592.     + AG... files for the Assembler generation
  1593.  
  1594.   Revision 1.20  1998/03/06 00:52:44  peter
  1595.     * replaced all old messages from errore.msg, only ExtDebug and some
  1596.       Comment() calls are left
  1597.     * fixed options.pas
  1598.  
  1599.   Revision 1.19  1998/03/02 01:49:02  peter
  1600.     * renamed target_DOS to target_GO32V1
  1601.     + new verbose system, merged old errors and verbose units into one new
  1602.       verbose.pas, so errors.pas is obsolete
  1603.  
  1604.   Revision 1.18  1998/03/01 22:46:18  florian
  1605.     + some win95 linking stuff
  1606.     * a couple of bugs fixed:
  1607.       bug0055,bug0058,bug0059,bug0064,bug0072,bug0093,bug0095,bug0098
  1608.  
  1609.   Revision 1.17  1998/02/27 21:24:06  florian
  1610.     * dll support changed (dll name can be also a string contants)
  1611.  
  1612.   Revision 1.16  1998/02/24 00:19:17  peter
  1613.     * makefile works again (btw. linux does like any char after a \ )
  1614.     * removed circular unit with assemble and files
  1615.     * fixed a sigsegv in pexpr
  1616.     * pmodule init unit/program is the almost the same, merged them
  1617.  
  1618.   Revision 1.15  1998/02/13 10:35:24  daniel
  1619.   * Made Motorola version compilable.
  1620.   * Fixed optimizer
  1621.  
  1622.   Revision 1.14  1998/02/12 17:19:20  florian
  1623.     * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1624.       also that aktswitches isn't a pointer)
  1625.  
  1626.   Revision 1.13  1998/02/12 11:50:26  daniel
  1627.   Yes! Finally! After three retries, my patch!
  1628.  
  1629.   Changes:
  1630.  
  1631.   Complete rewrite of psub.pas.
  1632.   Added support for DLL's.
  1633.   Compiler requires less memory.
  1634.   Platform units for each platform.
  1635.  
  1636.   Revision 1.12  1998/02/11 21:56:37  florian
  1637.     * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
  1638.  
  1639.   Revision 1.11  1998/02/01 22:41:11  florian
  1640.     * clean up
  1641.     + system.assigned([class])
  1642.     + system.assigned([class of xxxx])
  1643.     * first fixes of as and is-operator
  1644.  
  1645.   Revision 1.10  1998/02/01 15:04:15  florian
  1646.     * better error recovering
  1647.     * some clean up
  1648.  
  1649.   Revision 1.9  1998/01/30 21:27:05  carl
  1650.     * partial bugfix #88, #89 and typeof and other inline functions
  1651.       (these bugs have a deeper nesting level, and therefore i only fixed
  1652.        the parser crashes - there is also a tree crash).
  1653.  
  1654.   Revision 1.8  1998/01/26 17:31:01  florian
  1655.     * stupid bug with self in class methods fixed
  1656.  
  1657.   Revision 1.7  1998/01/25 22:29:02  florian
  1658.     * a lot bug fixes on the DOM
  1659.  
  1660.   Revision 1.6  1998/01/23 10:46:41  florian
  1661.     * small problems with FCL object model fixed, objpas?.inc is compilable
  1662.  
  1663.   Revision 1.5  1998/01/16 22:34:42  michael
  1664.   * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
  1665.     in this compiler :)
  1666.  
  1667.   Revision 1.4  1998/01/16 18:03:15  florian
  1668.     * small bug fixes, some stuff of delphi styled constructores added
  1669.  
  1670.   Revision 1.3  1998/01/13 23:11:14  florian
  1671.     + class methods
  1672.  
  1673.   Revision 1.2  1998/01/09 09:09:59  michael
  1674.   + Initial implementation, second try
  1675.  
  1676. }
  1677.